<template>
    <div class="background">
        <ChatNav></ChatNav>

        <div class="main">
            <div class="chat-aside">
                <div class="aside-top" @click="promptMessage()">
                    <i class="el-icon-chat-dot-square"></i>
                    <div class="friend-text">群聊</div>
                </div>
                <div class="aside-top" @click="promptMessage()">
                    <i class="el-icon-s-custom"></i>
                    <div class="friend-text">好友</div>
                </div>
                <div class="aside-buttom" @click="promptMessage()">
                    <i class="el-icon-s-tools"></i>
                    <div class="friend-text">设置</div>
                </div>
            </div>

            <div class="chat-left">
                <el-menu class="left-menu" default-active="-1" active-text-color="#ffd04b">
                    <el-menu-item class="left-menu-item" v-for="(item, index) in chatList" :index="index.toString()"
                        :key="index" @click="handleClick(index)">
                        <img class="chat-cover" :src="downloadUrl + item.chatCover" />
                        <span class="chat-title">{{ item.chatTitle }}</span>
                    </el-menu-item>
                </el-menu>
            </div>

            <div class="chat-box" v-show="showChatBox">
                <div class="chat-header">
                    <span class="chat-name">聊天室：{{ chatActive.chatTitle }}</span>
                    <span class="chat-number">聊天室人数: {{ chatActive.peopleNum }}</span>
                </div>
                <div class="chat-message" ref="chat-message">
                    <div :class="item.sendUserId === userInfo.id ? 'message-right' : 'message-left'"
                        v-for="(item, index) in messageList" :key="index">
                        <span class="sendUserName">{{ item.sendUserName }}</span>
                        <span class="message">{{ item.message }}</span>
                        <span class="messageDate">{{ item.messageDate }}</span>
                    </div>
                </div>
                <div class="chat-bottom">
                    <!-- 输入框 -->
                    <textarea class="message-content" @keydown="send($event)" v-model="contentText" maxlength="1000"
                        spellcheck="false"></textarea>
                    <div class="message-send">
                        <span class="sendTips">Ctrl+Enter：换行 | Enter：发送</span>
                        <el-button ref="sendText" @click="sendText()" type="primary">发送消息</el-button>
                        <el-button class="closeText" @click="closeText()">关闭消息框</el-button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
  
<script>
import { getUserChats, updateChatUser, getChatUserCount } from "@/api/other/chatUser";

import ChatNav from "@/views/chat/ChatNav";

export default {
    name: "MyChat",
    components: {
        ChatNav,
    },
    data() {
        return {
            userInfo: this.$store.getters.userInfo,
            // 聊天室列表
            chatList: [],
            // 当前激活的聊天室
            chatActive: {},
            chatActiveId: this.$route.query.keyword,
            // 定时器，定时查询在线人数
            timer: "",

            // 消息框
            showChatBox: false,
            messageAllMap: new Map(),
            messageList: [],
            // input输入的值
            contentText: '',

            // 用于记录已经创建的websocket，防止重复创建
            webSocketIdSet: new Set(),
            // 用于保存多组websocket
            websocketMap: new Map(),

            // 后台地址
            downloadUrl: process.env.VUE_APP_DOWNLOAD_URL,
            chatSocketUrl: process.env.VUE_APP_CHATSOCKET_URL,
        }
    },

    created() {
        this.getUserChats();
    },
    mounted() {
        // 定时任务，获取当前在线人数
        this.timer = setInterval(() => {
            this.getChatUserCount();
        }, 20000)
    },

    methods: {
        // 获取用户的聊天室
        async getUserChats() {
            const { data: res } = await getUserChats(this.userInfo.id);
            this.chatList = res.data;
            // 如果是通过进入群聊按钮进来的，激活该聊天室
            if (this.chatActiveId) {
                // 遍历list，找到要激活的聊天室
                for (var i = 0; i < this.chatList.length; i++) {
                    if (this.chatList[i].chatId == this.chatActiveId) {
                        this.chatActive = this.chatList[i];
                        this.getWebSocket();
                        return;
                    }
                }
            }
        },
        async getChatUserCount() {
            if (this.chatActive.chatId) {
                const { data: res } = await getChatUserCount(this.chatActive.chatId);
                this.chatActive.peopleNum = res.data;
            }
        },

        handleClick(index) {
            this.chatActive = this.chatList[index];
            console.log("聊天室 : " + index + " 被点击了");
            this.getWebSocket();
        },
        getWebSocket() {
            if (typeof (WebSocket) == "undefined") {
                console.log("您的浏览器不支持WebSocket");
            } else {
                // 注意要转为数字格式
                this.connectWebSocket(this.chatActive.chatId);
                this.showChatBox = true;

                // 获取存储的聊天记录
                this.messageList = [];
                if (this.messageAllMap.has(this.chatActive.chatId)) {
                    // 对象深拷贝，修改不影响之前的
                    this.messageList = this.$lodash.cloneDeep(this.messageAllMap.get(this.chatActive.chatId));
                } else {
                    console.log('map中的数据 : ', JSON.stringify([...this.messageAllMap.entries()]));
                }
                setTimeout(() => {
                    this.scrollBottm();
                }, 100);
                // 更新用户最后进入聊天室的时间
                this.chatActive.userLastIn = new Date();
                updateChatUser(this.chatActive);
            }
        },

        connectWebSocket(webSocketId) {
            // 防止重复连接
            if (!this.webSocketIdSet.has(webSocketId)) {
                console.log('开启socket : ' + webSocketId);
                this.webSocketIdSet.add(webSocketId);
                const websocket = new WebSocket(this.chatSocketUrl + webSocketId);
                this.websocketMap.set(webSocketId, websocket);
                this.initWebSocket(webSocketId);
            }
        },
        initWebSocket(webSocketId) {
            // 连接成功
            this.websocketMap.get(webSocketId).onopen = this.setOnOpen;
            // 收到消息的回调
            this.websocketMap.get(webSocketId).onmessage = this.setOnMessage;
            // 连接错误
            this.websocketMap.get(webSocketId).onerror = this.setError;
            // 连接关闭的回调
            this.websocketMap.get(webSocketId).onclose = this.setOnClose;
            // 监听窗口关闭事件，当窗口关闭时，主动去关闭所有websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
            window.onbeforeunload = this.onbeforeunload;
        },

        setOnMessage(event) {
            console.log('OnMessage返回的数据 : ', event);
            const url = event.target.url;
            const webSocketId = parseInt(url.substring(url.lastIndexOf('/') + 1));
            let returnData = JSON.parse(event.data);
            // 若只返回了一个对象，转为List
            if (!Array.isArray(returnData)) {
                returnData = [returnData];
            }
            // 数组反向排序
            returnData.reverse();
            // 获取该房间的旧的聊天记录
            let messageOrigin = [];
            if (this.messageAllMap.has(webSocketId)) {
                messageOrigin = this.messageAllMap.get(webSocketId);
            }
            // 存入新传来的消息
            for (var i = 0; i < returnData.length; i++) {
                let messageNew = {};
                messageNew.chatId = returnData[i].chatId;
                messageNew.message = returnData[i].message;
                messageNew.sendUserId = returnData[i].userId;
                messageNew.sendUserName = returnData[i].userName;
                messageNew.messageDate = this.dateTransform(returnData[i].createTime);
                messageOrigin.push(messageNew);
                // 判断是否是当前打开的聊天室
                if (webSocketId === this.chatActive.chatId) {
                    this.messageList.push(messageNew);
                }
            }
            // this.messageAllMap.set(webSocketId, messageOrigin);
        },
        setOnOpen(event) {
            console.log('OnOpen返回的数据 : ', event);
        },
        setError(event) {
            console.log('OnError返回的数据 : ', event);
        },
        setOnClose(event) {
            console.log('OnClose返回的数据 : ', event);
            const url = event.target.url;
            const webSocketId = parseInt(url.substring(url.lastIndexOf('/') + 1));
            // 若是当前打开的房间，关闭聊天室
            if (this.chatActive.chatId === webSocketId) {
                this.showChatBox = false;
            }
            console.log('websocketMap中的数据 : ', JSON.stringify([...this.websocketMap.entries()]));
            console.log('WebSocket连接关闭：' + webSocketId);
        },

        onbeforeunload() {
            this.closeWebSocket(null);
            // 清除多次执行定时器
            clearInterval(this.timer);
        },
        // 当参数为空时关闭所有webSocket,否则关闭键为webSocketId的webSocket
        closeWebSocket(webSocketId) {
            if (webSocketId == null) {
                console.log("聊天室全部关闭");
                this.websocketMap.forEach((webSocket, webSocketId) => {
                    if (webSocket !== null) {
                        webSocket.close();
                        this.websocketMap.delete(webSocketId);
                        this.webSocketIdSet.delete(webSocketId);
                    }
                })
            } else {
                if (this.websocketMap.get(webSocketId) !== null) {
                    this.websocketMap.get(webSocketId).close();
                    this.websocketMap.delete(webSocketId);
                    this.webSocketIdSet.delete(webSocketId);
                }
            }
        },

        send(e) {
            if (e && (e.ctrlKey || e.shiftKey) && e.keyCode === 13) {
                e.returnValue = false;
                this.sendText();
            } else if (e && e.keyCode === 13) {
                e.returnValue = false;
                this.sendText();
            }
        },
        // 发送消息
        sendText() {
            let _this = this;
            console.log("发送消息：" + _this.contentText);
            if (!_this.contentText) {
                return false;
            }
            let params = {
                userId: _this.userInfo.id,
                chatId: _this.chatActive.chatId,
                message: _this.contentText.toString(),
            };
            this.websocketMap.get(this.chatActive.chatId).send(JSON.stringify(params));
            this.contentText = "";
            setTimeout(() => {
                _this.scrollBottm();
            }, 100);
        },
        // 滚动条到底部
        scrollBottm() {
            let el = this.$refs['chat-message'];
            el.scrollTop = el.scrollHeight;
        },
        // 关闭聊天消息框
        closeText() {
            this.showChatBox = false;
            // this.messageAllMap.delete(this.chatActive.chatId);
            // this.closeWebSocket(null);
        },

        // 日期格式转换
        dateTransform(date) {
            const da = new Date(date);
            let year = da.getFullYear();
            let month = da.getMonth() + 1;
            month = month < 10 ? "0" + month : month;
            let day = da.getDate();
            day = day < 10 ? "0" + day : day;
            let h = ' ' + da.getHours() + ':';
            let m = da.getMinutes() + ':';
            let s = da.getSeconds();
            if (year === new Date().getFullYear()) {
                return month + "-" + day + h + m + s;
            } else {
                return year + "-" + month + "-" + day + h + m + s;
            }
        },
        // 提示信息
        promptMessage() {
            this.$message.warning("此页面还没有做好哦!");
        },
    },

    // 关闭页面前触发
    beforeDestroy() {
        this.closeWebSocket(null);
        // 清除多次执行定时器
        clearInterval(this.timer);
    },
}

</script>
  
<style scoped>
.background {
    background-image: url("../../assets/theme/beijing.jpg");
    background-size: cover;
    /* background-repeat: no-repeat; */
    background-position: center;
    animation: run 60s linear infinite;
    width: 100%;
    height: calc(100vh - 60px);
    overflow: hidden;
}

@keyframes run {
    from {
        background-position: 0 0;
    }

    to {
        background-position: 100vw 0;
    }
}

.main {
    display: flex;
    width: 1000px;
    height: 600px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
    overflow: hidden;
    background-color: rgba(255, 255, 255, 0.8);
    border-radius: 10px;
    border: 2px solid rgba(152, 152, 152, 0.2);
}

.chat-aside {
    width: 60px;
    height: 100%;
    display: flex;
    flex-direction: column;
    border-right: 2px solid rgba(152, 152, 152, 0.2);
}

.aside-top {
    margin-top: 25px;
    text-align: center;
    cursor: pointer;
}

.aside-buttom {
    margin-top: 25px;
    text-align: center;
    cursor: pointer;
}

.friend-text {
    font-size: 13px;
}

.chat-left {
    width: 30%;
    height: 100%;
    border-right: 2px solid rgba(152, 152, 152, 0.2);
    overflow-y: scroll;
}

/* 隐藏滚动条 */
.chat-left::-webkit-scrollbar {
    display: none
}

.left-menu {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.chat-cover {
    width: 50px;
    height: 50px;
    border-radius: 50%;
}

.left-menu-item {
    display: flex;
    align-items: center;
    height: 70px;
}

.chat-title {
    width: 70%;
    height: 40px;
    line-height: 20px;
    overflow: hidden;
    margin-left: 15px;
    white-space: normal;
    word-break: break-all;
}

.chat-box {
    /* display: flex; */
    width: 65%;
    height: 100%;
}

.chat-header {
    display: flex;
    justify-content: space-between;
    /* justify-content: center; */
    align-items: center;
    height: 50px;
    padding: 0 20px;
    background: rgb(146, 194, 231);
    color: #fff;
    font-size: 18px;
}

.chat-name {
    overflow: hidden;
    width: 300px;
    height: 25px;
}

.chat-message {
    height: 400px;
    overflow-y: scroll;
    background: rgb(239, 239, 239);
}

.message-left {
    margin: 10px;
    display: flex;
    align-items: flex-start;
}

.message-left .message {
    border-radius: 0 4px 4px 4px;
    background: rgb(183, 239, 150);
}

.message-right {
    margin: 10px;
    display: flex;
    align-items: flex-start;
    flex-direction: row-reverse;
}

.message-right .message {
    border-radius: 4px 0 4px 4px;
    background-color: rgb(74, 222, 233);
}

.messageDate {
    font-size: 10px;
    color: grey;
}

.sendUserName {
    font-size: 16px;
    color: burlywood;
}

.message {
    max-width: 65%;
    padding: 4px 10px;
    margin: 0 10px;
    position: relative;
    line-height: 24px;
    font-size: 14px;
    word-break: break-all;
}

.chat-bottom {
    width: 100%;
    height: 120px;
}

.message-content {
    width: calc(100% - 30px);
    height: calc(100% - 30px);
    margin: 10px;
    box-sizing: border-box;
    display: block;
    border: none;
    outline: none;
    box-shadow: none;
    resize: none;
    font-size: 16px;
}

.message-send {
    float: right;
}

.sendTips {
    margin-right: 15px;
    font-size: 12px;
    color: grey;
}

.closeText {
    margin-right: 10px;
}
</style>